package com.sita.bike.rest;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sita.bike.rest.model.AccountListResponse;
import com.sita.bike.rest.model.AddRequest;
import com.sita.bike.rest.model.AdvertisementParams;
import com.sita.bike.rest.model.AdvertisementResponse;
import com.sita.bike.rest.model.CommentListRequestParams;
import com.sita.bike.rest.model.CommentListResponse;
import com.sita.bike.rest.model.FriendActionsRequest;
import com.sita.bike.rest.model.GroupCreateRequest;
import com.sita.bike.rest.model.ListResponseData;
import com.sita.bike.rest.model.ListUserRequest;
import com.sita.bike.rest.model.LoginRequest;
import com.sita.bike.rest.model.RtResourceNearRequest;
import com.sita.bike.rest.model.NewRankRequestParams;
import com.sita.bike.rest.model.NewRankResponse;
import com.sita.bike.rest.model.RangeListResponse;
import com.sita.bike.rest.model.RankResponse;
import com.sita.bike.rest.model.ResourceCommentRequest;
import com.sita.bike.rest.model.ResourceCommentResponse;
import com.sita.bike.rest.model.ResourceFetchParams;
import com.sita.bike.rest.model.ResourceFetchResponse;
import com.sita.bike.rest.model.ResourceListParams;
import com.sita.bike.rest.model.ResourceListResponse;
import com.sita.bike.rest.model.RestResponse;
import com.sita.bike.rest.model.RtResourceListRequest;
import com.sita.bike.rest.model.SearchNearlyPersonRequest;
import com.sita.bike.rest.model.SearchResponse;
import com.sita.bike.rest.model.SearchUserRequest;
import com.sita.bike.rest.model.ThirdPartyRegisterRequestParams;
import com.sita.bike.rest.model.request.GetAccountRequest;
import com.sita.bike.rest.model.request.GetRtResourceCountRequest;
import com.sita.bike.rest.model.request.ResStatisticsRequest;
import com.sita.bike.rest.model.request.ResourceListByAccountRequest;
import com.sita.bike.rest.model.request.RtBlacklistRequest;
import com.sita.bike.rest.model.request.RtDeLikeResourceRequest;
import com.sita.bike.rest.model.request.RtDelResourceRequest;
import com.sita.bike.rest.model.request.RtLeaveNoteListRequest;
import com.sita.bike.rest.model.request.RtLeaveNoteNewRequest;
import com.sita.bike.rest.model.request.RtLikeResourceRequest;
import com.sita.bike.rest.model.request.UpdateGeoRequest;
import com.sita.bike.rest.model.response.GetAccountResponse;
import com.sita.bike.rest.model.response.MileageSummaryRankingResponse;
import com.sita.bike.rest.model.response.MileageSummaryResponse;
import com.sita.bike.rest.model.response.RtBlacklistResponse;
import com.sita.bike.rest.model.response.RtDelResourceResponse;
import com.sita.bike.rest.model.response.RtResourceDelikeResponse;
import com.sita.bike.rest.model.response.RtResourceLikeResponse;
import com.sita.bike.rest.model.response.RtResourceNoteListResponse;
import com.sita.bike.rest.model.response.RtResourceNoteNewResponse;
import com.sita.bike.rest.model.response.RtResourcesCountResponse;
import com.sita.bike.rest.model.response.RtResourcesList4AccountResponse;
import com.sita.bike.rest.model.response.RtResourcesListResponse;
import com.sita.bike.rest.model.response.SyncTrackListResponse;
import com.sita.bike.support.Constants;
import com.sita.tingterest.pojo.CategoryRequest;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Response;

import java.util.Map;
import java.util.concurrent.TimeUnit;

import retrofit.Callback;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.client.OkClient;
import retrofit.converter.GsonConverter;
import retrofit.http.Body;
import retrofit.http.GET;
import retrofit.http.Multipart;
import retrofit.http.POST;
import retrofit.http.PUT;
import retrofit.http.Part;
import retrofit.http.Path;
import retrofit.http.Query;
import retrofit.http.QueryMap;
import retrofit.http.Streaming;
import retrofit.mime.TypedFile;
import retrofit.mime.TypedString;

public class RestClient {
    private static final String BASE_URL = Constants.BASE_URI;
    private static RestService restService;
    private static RestService restNormalService;
    private static Gson mGson = new GsonBuilder()
            .setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
            .serializeNulls()
            .create();

    private static Gson mGson2 = new GsonBuilder()
            .setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
            .create();

    private static RequestInterceptor restInterceptor = new RequestInterceptor() {
        @Override
        public void intercept(RequestFacade request) {
            request.addHeader("Content-Type", Constants.APPLICATION_JSON);
            request.addHeader("Accept", Constants.APPLICATION_JSON);
        }
    };

    private static RequestInterceptor restFormInterceptor = new RequestInterceptor() {
        @Override
        public void intercept(RequestFacade request) {
            request.addHeader("Accept", Constants.APPLICATION_JSON);
        }
    };

    private static void createRestFormClient() {
        final OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
        okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);
        okHttpClient.setWriteTimeout(120, TimeUnit.SECONDS);

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setEndpoint(BASE_URL)
                .setConverter(new GsonConverter(mGson))
                .setRequestInterceptor(restFormInterceptor)
                .setClient(new OkClient(okHttpClient))
                .build();

        restService = restAdapter.create(RestService.class);
    }

    private static void createRestNormalClient() {
        final OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
        okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);
        okHttpClient.setWriteTimeout(120, TimeUnit.SECONDS);

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setEndpoint(BASE_URL)
                .setConverter(new GsonConverter(mGson))
                .setRequestInterceptor(restInterceptor)
                .setClient(new OkClient(okHttpClient))
                .build();

        restNormalService = restAdapter.create(RestService.class);
    }

    public static RestService getRestService() {
        if (restService == null) {
            createRestFormClient();
        }
        return restService;
    }

    public static RestService getRestNormalService() {
        if (restNormalService == null) {
            createRestNormalClient();
        }
        return restNormalService;
    }

    public static Gson getGson() {
        return mGson;
    }

    public static Gson getGsonNull() {
        return mGson2;
    }

    public interface RestService {
        @Multipart
        @POST("/usermgmt/v1/accounts/register")
        void register(@Part("params") TypedString params, Callback<RestResponse> callback);

        @Multipart
        @POST("/usermgmt/v1/accounts/update")
        void update(@Part("avatar") TypedFile header, @Part("params") TypedString params, Callback<RestResponse> callback);

        @POST("/usermgmt/v1/accounts/login")
        void login(@Body LoginRequest request, Callback<RestResponse> callback);

        @POST("/usermgmt/v1/accounts/search")
        void search(@Body SearchUserRequest request, Callback<SearchResponse> callback);

        @POST("/usermgmt/v1/friends/add")
        void add(@Body AddRequest request, Callback<RestResponse> callback);

        @POST("/usermgmt/v1/friends/reject")
        void reject(@Body AddRequest request, Callback<RestResponse> callback);

        @POST("/usermgmt/v1/friends/accept")
        void accept(@Body AddRequest request, Callback<RestResponse> callback);

        @POST("/usermgmt/v1/friends/list")
        void listUser(@Body ListUserRequest request, Callback<RestResponse> callback);

        @POST("/tinterest/v1/category/list")
        void categoryList(@Body CategoryRequest request, Callback<ListResponseData> callback);

        @POST("/usermgmt/v1/actions")
        void actions(@Body FriendActionsRequest request, Callback<RestResponse> callback);

        @POST("/roadtrust/v1/resources/fetch")
        void fetchOneResource(@Body ResourceFetchParams params, Callback<ResourceFetchResponse> callback);

        @POST("/usermgmt/v1/accounts/register3rd")
        void thirdPartyRegister(@Body ThirdPartyRegisterRequestParams request, Callback<RestResponse> callback);

        @POST("/usermgmt/v1/accounts/login3rd")
        void thirdPartyLogin(@Body ThirdPartyRegisterRequestParams request, Callback<RestResponse> callback);

        @POST("/usermgmt/v1/accounts/list/geofence")
        void searchNearlyAccounts(@Body SearchNearlyPersonRequest request, Callback<AccountListResponse> callback);

        @GET("/usermgmt/v1/accounts")
        void listAccounts(@Query("page") int pageNumber, @Query("size") int pageSize, Callback<AccountListResponse> callback);

        @POST("/usermgmt/v1/groups/new")
        void newGroup(@Body GroupCreateRequest request, Callback<RestResponse> callback);

        @GET("/usermgmt/v1/groups/{groupid}")
        void getGroupDetail(@Path("groupid") String groupId, @Query("im") boolean isImGroup, Callback<RestResponse> callback);

//        @POST("/roadtrust/v1/range/list")
//        void getDynamicState(@Body RtResourceListRequest request, Callback<RtResourcesList4AccountResponse> callback);


        @POST("/tinterest/v1/resources/list")
        void getResourceList(@Body ResourceListParams request, Callback<ResourceListResponse> callback);

        @POST("/roadtrust/v1/notes/new")
        void addResourceComment(@Body ResourceCommentRequest request, Callback<ResourceCommentResponse> callback);

        @POST("/roadtrust/v1/notes/list")
        void getCommentList(@Body CommentListRequestParams request, Callback<CommentListResponse> callback);

        @Multipart
        @POST("/usermgmt/v1/messages")
        void sendMessage(@Part("accountId") TypedString accountId,
                         @Part("targetType") TypedString targetType,
                         @Part("targetId") TypedString targetId,
                         @Part("message") TypedString message,
                         Callback<RestResponse> callback);

        @POST("/usermgmt/v1/mileages/new")
        void sendNewRanking(@Body NewRankRequestParams request, Callback<NewRankResponse> callback);

        @POST("/tinterest/v1/advertisinges/getone")
        void getAdvertisementData(@Body AdvertisementParams request, Callback<AdvertisementResponse> callback);

        @POST("/roadtrust/v1/resources/vote")
        void resourceLike(@Body RtLikeResourceRequest request, Callback<RtResourceLikeResponse> callback);

        @POST("/roadtrust/v1/resources/devote")
        void resourceDelike(@Body RtDeLikeResourceRequest request, Callback<RtResourceDelikeResponse> callback);

        @POST("/roadtrust/v1/resources/list")
        void rtResourceList(@Body RtResourceListRequest request, Callback<RtResourcesListResponse> callback);

        @POST("/roadtrust/v1/resources/near")
        void rtResourceNear(@Body RtResourceNearRequest request, Callback<RangeListResponse> callback);

        @POST("/roadtrust/v1/resources/get")
        void rtResourceListByAccount(@Body ResourceListByAccountRequest request, Callback<RtResourcesList4AccountResponse> callback);

        @POST("/roadtrust/v1/notes/new")
        void rtResourceNewNote(@Body RtLeaveNoteNewRequest request, Callback<RtResourceNoteNewResponse> callback);

        @POST("/roadtrust/v1/notes/list")
        void rtResourceListNote(@Body RtLeaveNoteListRequest request, Callback<RtResourceNoteListResponse> callback);

        @POST("/usermgmt/v1/accounts/obtain")
        void accountGet(@Body GetAccountRequest request, Callback<GetAccountResponse> callback);

	    /**
	     * For query on person, forSelf=true
	     * @param params key can be accountId, startTime, endTime
	     * @param callback
	     */
        @GET("/usermgmt/v1/mileages/summaries?forSelf=true")
        void mileageSummaryForAccount(@QueryMap Map<String, String> params, Callback<MileageSummaryResponse> callback);

	    /**
	     *
	     * @param params key can be accountId, startTime, endTime
	     * @param callback
	     */
        @GET("/usermgmt/v1/mileages/summaries")
        void mileageSummaryForFriends(@QueryMap Map<String, String> params, Callback<MileageSummaryResponse> callback);

        @GET("/usermgmt/v1/mileages/summaries")
        void getRanking(@Query("accountId") String accountId, Callback<RankResponse> callback);

        @GET("/usermgmt/v1/mileages/summaries/ranking")
        void mileageSummaryRanking(@Query("accountId") String accountId, Callback<MileageSummaryRankingResponse> callback);

        @POST("/roadtrust/v1/resources/count")
        void rtResourcesCount(@Body GetRtResourceCountRequest request, Callback<RtResourcesCountResponse> callback);

        @POST("/roadtrust/v1/accounts/{accountId}/blacklists")
        void rtAddBlacklist(@Path("accountId") String accountId, @Body RtBlacklistRequest request,
                            Callback<RtBlacklistResponse> callback);

        @PUT("/roadtrust/v1/accounts/{accountId}/blacklists")
        void rtUpdateBlacklist(@Path("accountId") String accountId, @Body RtBlacklistRequest request,
                               Callback<RtBlacklistResponse> callback);

        @POST("/roadtrust/v1/resources/delete")
        void rtDeleteResource(@Body RtDelResourceRequest request, Callback<RtDelResourceResponse> callback);

        @Multipart
        @POST("/roadtrust/v1/accounts/{id}/routes")
        void uploadRoadTrust(@Path("id") String id,@Part("params") TypedString params, @Part("file")  TypedFile file, Callback<RestResponse> callback);

        @GET("/roadtrust/v1/accounts/{id}/routes")
        void syncTracksList(@Path("id") String accountId, Callback<SyncTrackListResponse> callback);

        @POST("/usermgmt/v1/accounts/updategeo")
        void updateGeo(@Body UpdateGeoRequest request, Callback<RestResponse> callback);

        @POST("/roadtrust/v1/resstatistics")
        void resStatistics(@Body ResStatisticsRequest request, Callback<RestResponse> callback);

    }

}
